package com.uxsino.simo.indicator.retractor;

import com.uxsino.commons.utils.StringUtils;
import com.uxsino.commons.utils.config.PropElement;
import com.uxsino.simo.indicator.Indicator;
import com.uxsino.simo.networkentity.EntityInfo;
import com.uxsino.simo.query.QueryContext;
import com.uxsino.simo.query.QueryTemplate;
import com.uxsino.simo.utils.ConfigLoadingContext;
import org.mvel2.MVEL;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;

public class HCNetStructureRetractor extends CompoundValueRetractor {

    private static final Logger logger = LoggerFactory.getLogger(HCNetStructureRetractor.class);

    protected Map<String, String> fieldMap = new LinkedHashMap<>(fieldRetrievers.size());

    @Override
    public Object doRetract(EntityInfo entity, QueryContext ctxt, QueryTemplate qt, Object obj) {
        HCNetStructureModel model = (HCNetStructureModel) obj;
        if (model == null || model.getStructures().isEmpty()) {
            return null;
        }

        Integer length = model.getLength();
        if (length != null && length > 32)
            length = 32;

        List<Object> list = model.getStructures();
        List<Map<String, Object>> res = new ArrayList<>();
        for (int i = 0; i < list.size(); i++) {
            Object o = list.get(i);
            if (o == null)
                continue;

            Map<String, Object> params = new HashMap<>();
            params.put("value", o);
            for (int j = 0; j < (length == null ? 1 : length); j++) {
                if (model.getEnables() == null || model.getEnables()[j]) {
                    Map<String, Object> structure = new LinkedHashMap<>();
                    structure.put("host", model.getHost());
                    structure.put("channel", 1 + j + i);
                    structure.put("name", 1 + j + i); // 用于listUnion
                    res.add(structure);

                    for (Map.Entry<String, String> entry : fieldMap.entrySet()) {
                        String formula = entry.getValue();
                        if (length == null && StringUtils.isStrictEmpty(formula)) {
                            // 对象数据给formula赋默认值
                            formula = "value." + entry.getKey();
                        } else if (length != null && StringUtils.isStrictNotEmpty(formula)) {
                            // 数组数据formula不为空时对index进行替换
                            if (formula.contains("$index$")) {
                                formula = formula.replaceAll("\\$index\\$", j + "");
                            }
                        }

                        if (StringUtils.isStrictNotEmpty(formula)) {
                            Object value = MVEL.eval(formula, params);
                            if (value instanceof String)
                                value = ((String) value).replaceAll("\u0000", "");

                            structure.put(entry.getKey(), value);
                        }
                    }
                }
            }
        }

        Object r;
        if (res.size() > 1 || length != null)
            r = res;
        else
            r = res.get(0);
        return transForm(r);
    }

    @Override
    public void loadProp(Indicator ind, PropElement eRetractor, ConfigLoadingContext lctxt) {
        super.loadProp(ind, eRetractor, lctxt);
        for (PropElement eFld : eRetractor.getElements("field")) {
            String fieldName = eFld.getProp("name");
            String formula = eFld.getProp("formula");
            fieldMap.put(fieldName, formula);
        }
    }
}
